package m.html.util;

import m.html.element.other.DisplayItem;
import m.system.exception.MException;
import m.system.util.ActionUtil;
import m.system.util.ArrayUtil;
import m.system.util.DateUtil;
import m.system.util.StringUtil;
import manage.util.DictionaryUtil;
import manage.util.excel.SheetCell;
import manage.util.excel.SheetRow;

import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

public class ExcelUtil {

	public static <T extends IVueListColumn> List<SheetRow> toHeadCell(VueListPage page,List<T> cols) {
		List<SheetRow> rows= new ArrayList<>();
		List<SheetCell> cells= new ArrayList<>();
		int max=0;
		for(IVueListColumn col : cols) {
			if(!page.isShowCol(col)) continue;
			if(col.getType().equals("image")) continue;
			if(col.getType().equals("index")) {
				cells.add(SheetCell.headCell("序号",col.getWidth(),col.getAlign().toString()));
				continue;
			}
			if(!col.isFalse()) {
				if(null!=col.getGroupTitle()&&col.getGroupTitle().length>max) max=col.getGroupTitle().length;
				cells.add(SheetCell.headCell(col.getTitle(),col.getWidth(),col.getAlign().toString()));
			}
		}
		for(int i=0;i<max;i++) {
			List<SheetCell> cs= new ArrayList<>();
			for(IVueListColumn col : cols) {
				if(!page.isShowCol(col)) continue;
				if(col.getType().equals("image")) continue;
				if(col.getType().equals("index")) {
					cs.add(SheetCell.headCell("序号",col.getWidth(),col.getAlign().toString()));
					continue;
				}
				if(!col.isFalse()) {
					if(null!=col.getGroupTitle()&&col.getGroupTitle().length>i) {
						cs.add(SheetCell.headCell(col.getGroupTitle()[i],col.getWidth(),"center"));
					}else {
						cs.add(SheetCell.headCell(col.getTitle(),col.getWidth(),col.getAlign().toString()));
					}
				}
			}
			rows.add(new SheetRow(10,cs.toArray(new SheetCell[] {})));
		}
		rows.add(new SheetRow(cells.toArray(new SheetCell[] {})));
		return rows;
	}
	public static <T extends IVueListColumn> List<SheetRow> toBodyCell(VueListPage page,List<T> cols, List<?> list, List<?> summary) throws ClassNotFoundException, MException {
		List<SheetRow> rows= new ArrayList<>();
		List<SheetCell> cells;
		for(int i=0;i<list.size();i++) {
			cells= new ArrayList<>();
			Object obj=list.get(i);
			for(IVueListColumn col : cols) {
				if(!page.isShowCol(col)) continue;
				if(col.getType().equals("image")) continue;
				if(col.getType().equals("index")) {
					cells.add(new SheetCell(String.valueOf(i+1),col.getWidth(),col.getAlign().toString()).setBorder(true,true,true,true));
					continue;
				}
				if(!col.isFalse()) {
					Object content=ActionUtil.getInAttribute(obj, col.getFieldAs());
					String tmp;
					if(null==content){
						tmp="";
					}else if(content instanceof Object[]){
						tmp=ArrayUtil.connection((Object[])content,",");
					}else{
						tmp=content.toString();
					}
					if(!StringUtil.isSpace(tmp)){
						if(!StringUtil.isSpace(col.getDateFormat())) {
							Date date;
							if(content instanceof LocalDateTime){
								Instant instant = ((LocalDateTime)content).toInstant(ZoneOffset.UTC);
								date=Date.from(instant);
							}else{
								date=(Date)content;
							}
							cells.add(new SheetCell(date,col.getDateFormat(),col.getWidth(),col.getAlign().toString()).setBorder(true,true,true,true));
						}else if(!StringUtil.isSpace(col.getNumberFormat())) {
							content=Double.parseDouble(tmp);
							cells.add(new SheetCell(content,col.getNumberFormat(),col.getWidth(),col.getAlign().toString()).setBorder(true,true,true,true));
						}else if(!StringUtil.isSpace(col.getDictType())) {
							content=DictionaryUtil.getName(col.getDictType(),content);
							cells.add(new SheetCell(content,col.getNumberFormat(),col.getWidth(),col.getAlign().toString()).setBorder(true,true,true,true));
						}else{
							StringBuilder tt=new StringBuilder();
							List<DisplayItem> items=col.getDisItems();
							if(items.isEmpty()) tt.append(tmp);
							else{
								List<String> arr= new ArrayList<>();
								if(content instanceof String[]) {
									arr.addAll(Arrays.asList((String[]) content));
								}else{
									arr.add(tmp);
								}
								for(int n=0;n<arr.size();n++){
									if(n>0) tt.append(",");
									for(DisplayItem item : items) {
										if(StringUtil.noSpace(item.getValue()).equals(arr.get(n))) {
											tt.append(item.getTitle());
										}
									}
								}
							}
							cells.add(new SheetCell(tt,col.getWidth(),col.getAlign().toString()).setBorder(true,true,true,true));
						}
					}else {
						cells.add(new SheetCell("",col.getWidth(),col.getAlign().toString()).setBorder(true,true,true,true));
					}
				}
			}
			rows.add(new SheetRow(cells.toArray(new SheetCell[] {})));
		}
		if(null!=summary&& !summary.isEmpty()){
			cells= new ArrayList<>();
			for(Object obj : summary){
				Object[] arr=(Object[]) obj;
				if(arr[4].equals("image")) continue;
				if(arr[4].equals("index")) {
					cells.add(new SheetCell("",100).setBorder(true,true,true,true));
					continue;
				}
				if((boolean)arr[5]) continue;
				String format=arr[1].toString();
				if(!StringUtil.isSpace(format)) {
					if(arr[0] instanceof Date){
						cells.add(new SheetCell(DateUtil.format((Date)arr[0],format),format,100,arr[2].toString()).setBorder(true,true,true,true));
					}else if(arr[0] instanceof LocalDateTime){
						Instant instant = ((LocalDateTime)arr[0]).toInstant(ZoneOffset.UTC);
						cells.add(new SheetCell(Date.from(instant),format,100,arr[2].toString()).setBorder(true,true,true,true));
					}else{
						cells.add(new SheetCell(Double.parseDouble(arr[0].toString()),format,100,arr[2].toString()).setBorder(true,true,true,true));
					}
				}else{
					cells.add(new SheetCell("",100).setBorder(true,true,true,true));
				}
			}
			rows.add(new SheetRow(cells.toArray(new SheetCell[] {})));
		}
		return rows;
	}
	public static List<Integer[]> toHeadMergeCells(List<SheetRow> headRow){
		List<Integer[]> mc= new ArrayList<>();
		List<Boolean[]> flag= new ArrayList<>();
		int max=0;
		for(int i=0;i<headRow.size();i++) {
			SheetCell[] scs=headRow.get(i).getCells();
			if(scs.length>max) max=scs.length;
			flag.add(new Boolean[scs.length]);
			String tmp="";
			int tip=0;
			for(int j=0;j<scs.length;j++) {
				SheetCell sc=scs[j];
				if(tmp.equals(sc.getContent())&&(i==0||flag.get(i-1)[j])) {
					flag.get(i)[j]=true;
				}else {
					if(j>0&&j-1!=tip) mc.add(new Integer[] {i,i,tip,j-1});
					tmp=toContent(sc.getContent(),sc.getFormat());
					tip=j;
					flag.get(i)[j]=false;
				}
			}
			if(scs.length-1!=tip) mc.add(new Integer[] {i,i,tip,scs.length-1});
		}
		for(int n=0;n<max;n++) {
			String tmp="";
			int tip=0;
			for(int i=0;i<headRow.size();i++) {
				SheetCell sc=headRow.get(i).getCells()[n];
				if(!tmp.equals(sc.getContent())) {
					if(i>0&&tip!=i-1) mc.add(new Integer[] {tip,i-1,n,n});
					tmp=toContent(sc.getContent(),sc.getFormat());
					tip=i;
				}
			}
			if(tip!=headRow.size()-1) mc.add(new Integer[] {tip,headRow.size()-1,n,n});
		}
		return mc;
	}
	public static List<Integer[]> toBodyMergeCells(int topRowNum,List<SheetRow> bodyRow,int passRow,int spanIndex,int spanNum){
		List<Integer[]> mc= new ArrayList<>();
		if(bodyRow.size()<=1) return mc;
		List<Boolean[]> flag= new ArrayList<>();
		for(int n=spanIndex;n<spanIndex+spanNum;n++) {
			String tmp="";
			int tip=0;
			flag.add(new Boolean[bodyRow.size()]);
			for(int i=0;i<bodyRow.size()-passRow;i++) {
				SheetCell sc=bodyRow.get(i).getCells()[n];
				if(tmp.equals(toContent(sc.getContent(), sc.getFormat())) && (n == spanIndex || flag.get(n - spanIndex - 1)[i]
				)) {
					flag.get(n-spanIndex)[i]=true;
					//
				}else {
					if(i>0&&tip!=i-1) mc.add(new Integer[] {tip+topRowNum,i-1+topRowNum,n,n});
					tmp=toContent(sc.getContent(),sc.getFormat());
					tip=i;
					flag.get(n-spanIndex)[i]=false;
				}
			}
			if(tip!=bodyRow.size()-1-passRow) mc.add(new Integer[] {tip+topRowNum,bodyRow.size()-1-passRow+topRowNum,n,n});
		}
		return mc;
	}
	public static String toContent(Object content,String format) {
		if(StringUtil.isSpace(format)) {
			return content.toString();
		}else if(content instanceof Number) {
			return new DecimalFormat(format).format(new Double(content.toString()));
		}else if(content instanceof Date) {
			return new SimpleDateFormat(format).format((Date)content);
		}
		return content.toString();
	}
}
